package algo3c3g3.model;

import algo3c3g3.model.action.*;
import org.jdom.Element;

import algo3c3g3.model.persistence.Persistable;
import algo3c3g3.model.persistence.Persistence;

/**
 * Clase principal del modelo de datos. Contiene todos los elementos del juego.
 */
public class Level implements Persistable
{
   
    private int maxNumberOfUnits, numberOfUnitsToSave;
    
    private int time, timeout;
    
    private ActionsAvailable actionsAvailable;
    
    private World world;
    
    /**
     * @param maxUnits Cantidad maxima de unidades del nivel.
     * @param unitsToSave Cantidad minima de unidades para salvar.
     * @param time Tiempo actual del nivel.
     * @param timeout Tiempo maximo para terminar el nivel.
     * @param world Mundo asociado.
     * @param actions Acciones disponibles en este nivel.
     */
    public Level(int maxUnits,
                 int unitsToSave,
                 int time,
                 int timeout,
                 World world,
                 ActionsAvailable actions)
    {
        maxNumberOfUnits = maxUnits;
        numberOfUnitsToSave = unitsToSave;
        this.time = time;
        this.timeout = timeout;
        this.world = world;
        actionsAvailable = actions;
    }
    
    public Level(Element e)
    {
        this.load(e);
    }
    
    public int getMaxUnitQty()
    {
        return maxNumberOfUnits;
    }
    
    public int getUnitQtyToSave()
    {
        return numberOfUnitsToSave;
    }
    
    public World getWorld()
    {
        return world;
    }
    
    public ActionsAvailable getActionsAvailable()
    {
        return actionsAvailable;
    }
    
    public int getTime()
    {
        return time;
    }
    
    public void incrementTime() {
    	time++;
    }
    
    public int getTiemOut()
    {
        return timeout;
    }
    
    /**
     * es el encargado de serializar la level.
     * @return el coord serializado dentro de un objeto Element
     */
    public Element save(){
    	Element root = new Element("Level");
    	root.addContent(new Element("maxNumberOfUnits").setText(Integer.toString( this.getMaxUnitQty())));
    	root.addContent(new Element("numberOfUnitsToSave").setText(Integer.toString( this.getUnitQtyToSave())));
    	root.addContent(new Element("time").setText(Integer.toString(time)));
    	root.addContent(new Element("timeout").setText(Integer.toString(timeout)));
    	root.addContent(getActionsAvailable().save());
    	root.addContent(this.getWorld().save());
    	return root;
    }
    
    /**
     * es el encargado de cargar un  level.
     * @return void, crea el objeto level y llama a todos los load de los objetos contenidos en level
     */
    public void load(Element e)
    {
        try
        {
            maxNumberOfUnits = Integer.parseInt(e.getChild("maxNumberOfUnits").getText());
            numberOfUnitsToSave = Integer.parseInt(e.getChild("numberOfUnitsToSave").getText());
            time = Integer.parseInt(e.getChild("time").getText());
            timeout = Integer.parseInt(e.getChild("timeout").getText());
        }
        catch (Exception exc)
        {
            exc.printStackTrace();
        }
        /**crear acciones**/
        Element actionsAvailable = e.getChild("algo3c3g3.model.ActionsAvailable");
        this.actionsAvailable = new ActionsAvailable(actionsAvailable);

        /**crear mundo**/
        Element ew = e.getChild("algo3c3g3.model.World");
        this.world = new World(ew);
    }
    
    public static void main(String[] args)
    {
    	System.out.println();
        
        // Carga un nivel de prueba.
        Level level1 = TestLevelFactory.newTestLevel1();
        
        // Obtiene componentes del nivel.
        World world = level1.getWorld();
        ActionsAvailable actions = level1.getActionsAvailable();
        
        System.out.println("Mapa:");
        world.printMap();
        
        // Si no se alcanzo el maximo de unidades de este nivel
        // agrega una unidad al mundo.
        if(world.getUnitQty() < level1.getMaxUnitQty())
            world.addUnit();
        
        Unit unit1 = world.getUnit(0);
        
        System.out.println("\nNueva unidad:");
        unit1.printStatus();
        
        // Asigna una accion de las que estan disponibles
        // si hay cantidad suficiente.
        if(actions.fetchAction(Basher.class) > 0)
            unit1.setAction(new Basher());
        
        unit1.printStatus();
        
        for(int i = 0; i < 5; i++)
        {
            world.moveUnits();
            unit1.printStatus();        
        }
        
        Persistence.toXMLFile(level1.save(),"C:\\salidaxx.xml");        
    }

}
